/*******************************************************************************
 * Copyright (c) 2012, 2013 XML-Print Project.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     XML-Print Project - initial API and implementation
 ******************************************************************************/
package info.xmlprint.run;

import info.xmlprint.ui.message.GuiMessages;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.eclipse.jface.dialogs.MessageDialog;

public class Configuration {

	private static Logger logger = Logger.getLogger(Configuration.class
			.toString());

	private String fontSelect;

	private File configFile;

	private String xmlprintRootDir, systemFontsDir, xmlprintTmpDir,
			xmlprintFontsDir, xmlprintConfigXml, eclipseRoot, userFontsDir,
			userWorkspace;

	private Map<String, String> attrMap;

	private String foFilePath, pdfFilePath, fontConfigXmlPath;

	private volatile static Configuration xmlprint_configuration;

	public String getEngineFilePath() {
		String engine = getEngineName();
		if (engine != null && engine.equalsIgnoreCase("xml-print")) {
			String enginePath = getEnginePath();
			if (enginePath == null || !new File(enginePath).canRead()) {
				MessageDialog.openError(null,
						GuiMessages.Stileditor_Error_Error,
						GuiMessages.Stileditor_Error_Engine);

				return null;
			}
			return enginePath.replaceAll("\\\\", "/");
		}
		return null;
	}

	public String getFoFilePath() {
		String time = new Date().getTime() + "";
		pdfFilePath = xmlprintTmpDir + time + ".pdf";
		foFilePath = xmlprintTmpDir + time + ".fo";
		fontConfigXmlPath = xmlprintTmpDir + time + "_font.xml";
		return foFilePath;
	}

	public String getFontConfigPathXml() {
		return fontConfigXmlPath;
	}

	public String getPdfFilePath() {
		return pdfFilePath;
	}

	public String getEclipseRoot() {
		return eclipseRoot;
	}

	public String getEngineName() {
		return getValueOf("engineName");
	}

	public String getEnginePath() {
		return getValueOf("enginePath");
	}

	private Configuration() {
		init();
	}

	public String getXmlprintRootDir() {
		return xmlprintRootDir;

	}

	public String getXmlprintTmpDir() {
		return xmlprintTmpDir;

	}

	public String getXmlprintConfigXml() {
		return xmlprintConfigXml;

	}

	public String getXmlprintFontsDir() {
		return xmlprintFontsDir;

	}

	public String getSystemFontsDir() {
		return systemFontsDir;
	}

	public String getUserFontsDir() {
		return userFontsDir;
	}

	public String getUserWorkspace() {
		return userWorkspace;
	}

	public static Configuration getInstance() {
		if (xmlprint_configuration == null) {
			synchronized (Configuration.class) {
				if (xmlprint_configuration == null) {
					xmlprint_configuration = new Configuration();
					logger.info("Configuration ... initiated\n");
				}
			}
		}
		return xmlprint_configuration;
	}

	public static boolean isOs(String osName) {
		Properties props = System.getProperties();
		String os = props.getProperty("os.name");
		Matcher m = Pattern.compile(osName, Pattern.CASE_INSENSITIVE).matcher(
				os);
		return m.find();
	}

	//
	private void init() {
		eclipseRoot = new File("").getAbsolutePath() + File.separator;
		String eclipseFileName = System.getProperty("eclipse.launcher");
		if (eclipseFileName != null) {
			File eclipseFile = new File(eclipseFileName);
			eclipseRoot = eclipseFile.getParentFile().getAbsolutePath() + File.separator;
		}

		// TODO: Benutzerverzeichnisse
		if (isOs("windows")) {
			systemFontsDir = System.getenv("SystemRoot") + "/fonts/";
			userFontsDir = "";
		} else if (isOs("linux")) {
			systemFontsDir = "/usr/share/fonts/";
			userFontsDir = "~/.fonts/";
		} else { // Mac OS
			systemFontsDir = "/Library/Fonts/";
			userFontsDir = "~/Library/Fonts/";
		}

		// xmlprintRootDir = eclipseRoot + "print/";

		String tempdir = System.getProperty("java.io.tmpdir");
		if (!(tempdir.endsWith("/") || tempdir.endsWith("\\")))
			tempdir = tempdir + System.getProperty("file.separator");

		xmlprintTmpDir = tempdir + "print" + File.separator;
		logger.info("Use temporary directory: " + xmlprintTmpDir);
		// xmlprintTmpDir = eclipseRoot + "print/temp/";

		// xmlprintConfigXml = eclipseRoot + "print/config.xml";

		String userdir = System.getProperty("user.home");
		if (!(userdir.endsWith("/") || userdir.endsWith("\\")))
			userdir = userdir + System.getProperty("file.separator");
		if (!isOs("windows") && !isOs("linux")) // for Mac
			xmlprintRootDir = userdir + "Library"
					+ System.getProperty("file.separator") + "XML-Print/";
		else
			xmlprintRootDir = userdir + ".xmlprint/";

		xmlprintConfigXml = xmlprintRootDir + "config.xml";

		xmlprintFontsDir = xmlprintRootDir + "fonts/";

		userWorkspace = userdir + "xmlprint";

		if (!createDir(xmlprintRootDir)) {
			logger.error(xmlprintRootDir + " not created");
			return;
		}

		if (!createDir(xmlprintFontsDir)) {
			logger.error(xmlprintFontsDir + " not created");
			return;
		}

		if (!createDir(xmlprintTmpDir)) {
			logger.error(xmlprintTmpDir + "not created");
			return;
		}

		if (!createDir(userWorkspace)) {
			logger.error(userWorkspace + "not created");
			return;
		}

		configFile = new File(xmlprintConfigXml);
	}

	private boolean createDir(String dirName) {
		File xmlprintDir = new File(dirName);
		if (!xmlprintDir.isDirectory()) {
			return xmlprintDir.mkdir();
		}
		return true;
	}

	public String getValueOf(String paramName) {
		if (testFile()) {
			SAXReader reader = new SAXReader();
			try {
				Document doc = reader.read(configFile);
				if (doc == null)
					return null;

				Node node = doc.getRootElement().selectSingleNode(paramName);
				if (node == null)
					return null;

				return node.getText();

			} catch (DocumentException e) {
				logger.error("", e);
				e.printStackTrace();
			}
		}

		return null;
	}

	/*
	 * Wenn kein configFile, erstellen
	 */
	private boolean testFile() {
		if (configFile.isFile())
			return true;
		else
			return createNewConfigXml();
	}

	public boolean setValue(String paramName, String paramValue) {
		if (!testFile())
			return false;

		return write(paramName, paramValue);

	}

	private boolean createNewConfigXml() {
		// init config values
		// engineName, enginePath, fontSelect
		fontSelect = "ttf otf type1";
		attrMap = new HashMap<String, String>();
		attrMap.put("fontSelect", fontSelect);
		attrMap.put("engineName", "XML-Print"); // default value
		if (isOs("windows") || isOs("linux")) {
			attrMap.put("enginePath", eclipseRoot
					+ "print/engine/XmlPrintEngine.exe");
		} else { // Mac
			String eclipseRootMac = eclipseRoot.substring(0,
					eclipseRoot.indexOf("xmlprint.app")); // get root directory
															// without .app
															// struture
			attrMap.put("enginePath", eclipseRootMac
					+ "print/engine/XmlPrintEngine.exe");
		}

		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("utf-8");
		format.setOmitEncoding(false);
		format.setExpandEmptyElements(false);

		Document doc = DocumentHelper.createDocument();
		Element root = doc.addElement("configuration");

		XMLWriter writer = null;
		try {
			writer = new XMLWriter(new FileWriter(configFile), format);
			for (String key : attrMap.keySet()) {
				root.addElement(key).setText(attrMap.get(key));
			}
			writer.write(doc);
			writer.close();
			return true;
		} catch (IOException e2) {
			e2.printStackTrace();
		}
		return false;
	}

	public boolean write(String param, String value) {

		if (param == null || value == null)
			return false;

		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("utf-8");
		format.setOmitEncoding(false);
		format.setExpandEmptyElements(false);
		try {

			SAXReader reader = new SAXReader();
			Document doc = reader.read(configFile);
			if (doc == null)
				return false;

			Element root = doc.getRootElement();

			XMLWriter writer = null;
			writer = new XMLWriter(new FileWriter(configFile), format);
			Node paramNode = root.selectSingleNode(param);
			if (paramNode == null) {
				root.addElement(param).setText(value);
			} else {
				paramNode.setText(value);
			}

			writer.write(doc);
			writer.close();
			return true;
		} catch (IOException e2) {
			e2.printStackTrace();
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		return false;
	}

}
